﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace SelfHosting.Handlers.Compression
{
    /// <summary>
    /// Représente la classe de base content
    /// </summary>
    public abstract class BaseContent : HttpContent
    {
        #region Constructeur

        /// <summary>
        /// Constructeur de la classe BaseContent
        /// </summary>
        /// <param name="content">Content original</param>
        /// <param name="compressor">Compresseur</param>
        public BaseContent(HttpContent content, ICompressor compressor)
        {
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }

            if (compressor == null)
            {
                throw new ArgumentNullException("compressor");
            }

            OriginalContent = content;
            Compressor = compressor;
       
            // copy the headers from the original content
            foreach (KeyValuePair<string, IEnumerable<string>> header in OriginalContent.Headers)
            {
                this.Headers.TryAddWithoutValidation(header.Key, header.Value);
            }

            this.Headers.ContentEncoding.Add(compressor.EncodingType);
        }

        #endregion

        #region Propriétés

        /// <summary>
        /// obtient ou définit content original
        /// </summary>
        private HttpContent OriginalContent { get; set; }

        /// <summary>
        /// Obtient ou définit le compresseur
        /// </summary>
        protected ICompressor Compressor { get; private set; }

        #endregion

        #region Méthodes

        /// <summary>
        /// 
        /// </summary>
        /// <param name="length"></param>
        /// <returns></returns>
        protected override bool TryComputeLength(out long length)
        {
            length = -1;
            return false;
        }

        /// <summary>
        /// Serialisation du stream
        /// </summary>
        /// <param name="stream">Stream</param>
        /// <param name="context"></param>
        /// <returns></returns>
        protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
        {
            Stream compressedStream = CreateStream(stream);
            return OriginalContent.CopyToAsync(compressedStream).ContinueWith(tsk =>
            {
                if (compressedStream != null)
                {
                    compressedStream.Dispose();
                }
            });
        }

        /// <summary>
        /// Création 
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        protected abstract Stream CreateStream(Stream stream);

        #endregion
    }
}
